home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / text / hyper / hsc_source.lha / hsc / source / hsclib / tag_hsc.c < prev    next >
C/C++ Source or Header  |  1996-12-04  |  26KB  |  941 lines

  1. /*
  2.  * hsclib/tag_hsc.c
  3.  *
  4.  * tag callbacks for "<$xx>" and related
  5.  * (for macro callbacks, see "tag_macr.c")
  6.  *
  7.  * Copyright (C) 1995,96  Thomas Aglassinger
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  *
  23.  * updated: 25-Nov-1996
  24.  * created: 23-Jul-1995
  25.  */
  26.  
  27. #include "hsclib/inc_tagcb.h"
  28.  
  29. #include "ugly/fname.h"
  30.  
  31. #include "hsclib/defattr.h"
  32. #include "hsclib/deftag.h"
  33. #include "hsclib/eval.h"
  34. #include "hsclib/include.h"
  35. #include "hsclib/parse.h"
  36. #include "hsclib/uri.h"
  37.  
  38. #include "hsclib/tag_macr.h"
  39. #include "hsclib/tag_if.h"
  40.  
  41. #define TIMEBUF_INC    20
  42. #define ES_STEP_SOURCE 1024
  43.  
  44. /* states for handle_hsc_source */
  45. #define SRST_TEXT    0          /* inside text      */
  46. #define SRST_LT      1          /* after "<"        */
  47. #define SRST_SLASH   2          /* after "</"       */
  48. #define SRST_CSOURCE 3          /* after "</$SOURCE" */
  49. #define SRST_TAG     8          /* inside a tag     */
  50. #define SRST_COMT    9          /* inside comment   */
  51. #define SRST_ERR    99          /* error occured    */
  52.  
  53. /* forward reference */
  54. BOOL handle_hsc_include(HSCPRC * hp, HSCTAG * tag);
  55.  
  56. /*
  57.  *-------------------------------------
  58.  * comment & skip handle (<* *>, <| |>)
  59.  *-------------------------------------
  60.  */
  61.  
  62. /*
  63.  * handle_hsc_comment
  64.  *
  65.  * skip text until '*>' occures;
  66.  * nested commets are supported
  67.  *
  68.  */
  69. BOOL handle_hsc_comment(HSCPRC * hp, HSCTAG * tag)
  70. {
  71.     BYTE cstate = CMST_TEXT;    /* vars for eoc_reached() */
  72.     LONG cnest = 0;             /* nesting: already read one "<*" */
  73.     BOOL end = FALSE;           /* end of comment reached? */
  74.  
  75.     while (!end && !(hp->fatal))
  76.     {
  77.         end = eoc_reached(hp, &cstate, &cnest);
  78.     }
  79.  
  80.     return (FALSE);
  81. }
  82.  
  83. /*
  84.  * handle_hsc_onlycopy
  85.  *
  86.  * copy text until '|>' occures;
  87.  * no syntax check or whatsoever is performed
  88.  *
  89.  * TODO: find more reasonable way to send output to client.
  90.  */
  91. BOOL handle_hsc_onlycopy(HSCPRC * hp, HSCTAG * tag)
  92. {
  93.     INFILE *inpf = hp->inpf;
  94.     int ch = EOF;               /* current char */
  95.     int prev_ch = EOF;          /* prev char read */
  96.     BOOL abort = FALSE;
  97.  
  98.     do
  99.     {
  100.         STRARR buf[3] =
  101.         {0, 0, 0};
  102.  
  103.         ch = infgetc(inpf);
  104.  
  105.         if ((prev_ch == '|') && (ch == '>'))
  106.         {
  107.             abort = TRUE;
  108.         }
  109.         else if ((prev_ch == '|') && (ch != '|'))
  110.         {
  111.             buf[0] = prev_ch;
  112.             buf[1] = ch;
  113.             hsc_output_text(hp, "", buf);
  114.         }
  115.         else if (ch != '|')
  116.         {
  117.             buf[0] = ch;
  118.             buf[1] = 0;
  119.             hsc_output_text(hp, "", buf);
  120.         }
  121.         abort |= infeof(inpf);
  122.         prev_ch = ch;
  123.     }
  124.     while (!abort);
  125.  
  126.     if (prev_ch == EOF)
  127.         hsc_msg_eof(hp, "skipping source");
  128.  
  129.     return (FALSE);
  130. }
  131.  
  132. /*
  133.  * handle_hsc_insert_expression
  134.  *
  135.  * insert value of a hsc-expression
  136.  *
  137.  * TODO: what to use as error-location, when inserting expression?
  138.  */
  139. BOOL handle_hsc_insert_expression(HSCPRC * hp, HSCTAG * tag)
  140. {
  141.     HSCATTR *dest = new_hscattr(PREFIX_TMPATTR "insert.expression");
  142.     STRPTR value = NULL;
  143.  
  144.     /* prepare dummy attribute */
  145.     dest->vartype = VT_STRING;
  146.  
  147.     /* compute expression */
  148.     value = eval_expression(hp, dest, ")");
  149.     if (value)
  150.     {
  151.         parse_gt(hp);
  152.         hsc_include_string(hp, SPECIAL_FILE_ID "insert expression", value,
  153.                            IH_PARSE_HSC | IH_NO_STATUS | IH_POS_PARENT);
  154.     }
  155.     del_hscattr(dest);
  156.  
  157.     return (FALSE);
  158. }
  159.  
  160. /*
  161.  *-------------------------------------
  162.  * $INCLUDE handle
  163.  *-------------------------------------
  164.  */
  165.  
  166. static VOID do_include(HSCPRC * hp, STRPTR filename,
  167.                        BOOL nostatus, BOOL temporary, BOOL source, BOOL pre,
  168.                        LONG indent, LONG tabsize)
  169. {
  170.     EXPSTR *fname = init_estr(0);
  171.     ULONG optn = 0;
  172.  
  173.     /* compute options */
  174.     if (!temporary)
  175.         optn |= IH_IS_INCLUDE;
  176.  
  177.     if (!nostatus)
  178.         optn |= IH_NO_STATUS;
  179.  
  180.     if (source)
  181.         optn |= IH_PARSE_SOURCE;
  182.  
  183.     /* compute filename (convert from URI if neccessary) */
  184. #define weenix jens /* TODO:remove this */
  185.     conv_uri2path(fname, filename, hp->weenix);
  186.  
  187.     /* insert leading <PRE> */
  188.     if (pre)
  189.     {
  190.         hsc_include_string(hp, SPECIAL_FILE_ID "include <PRE>", "<PRE>",
  191.                            IH_PARSE_HSC | IH_NO_STATUS | IH_POS_PARENT);
  192.     }
  193.     /* include main file */
  194.     if (fname)
  195.         hsc_include_file(hp, estr2str(fname), optn);
  196.  
  197.     /* insert tailing </PRE> */
  198.     if (pre)
  199.     {
  200.         hsc_include_string(hp, SPECIAL_FILE_ID "include </PRE>", "</PRE>\n",
  201.                            IH_PARSE_HSC | IH_NO_STATUS | IH_POS_PARENT);
  202.     }
  203.  
  204.     del_estr(fname);
  205. }
  206.  
  207. /*
  208.  * handle_hsc_include
  209.  *
  210.  * include a sub file
  211.  */
  212. BOOL handle_hsc_include(HSCPRC * hp, HSCTAG * tag)
  213. {
  214.     STRPTR fname_arg = get_vartext_byname(tag->attr, "FILE");
  215.     LONG indent = get_varnum_byname(tag->attr, "INDENT");
  216.     LONG tabsize = get_varnum_byname(tag->attr, "TABSIZE");
  217.     BOOL source = get_varbool_byname(tag->attr, "SOURCE");
  218.     BOOL pre = get_varbool_byname(tag->attr, "PRE");
  219.     BOOL temporary = get_varbool_byname(tag->attr, "TEMPORARY");
  220.  
  221.     do_include(hp, fname_arg, FALSE /*nostatus */ , temporary,
  222.                source, pre, indent, tabsize);
  223.  
  224.     return (FALSE);
  225. }
  226.  
  227. /*
  228.  *-------------------------------------
  229.  * $MESSAGE handle
  230.  *-------------------------------------
  231.  */
  232.  
  233. /*
  234.  * handle_hsc_error
  235.  *
  236.  * user error message
  237.  */
  238. BOOL handle_hsc_message(HSCPRC * hp, HSCTAG * tag)
  239. {
  240.     STRPTR msg_text = get_vartext_byname(tag->attr, "TEXT");
  241.     STRPTR msg_class = get_vartext_byname(tag->attr, "CLASS");
  242.  
  243.     if (msg_text)
  244.     {
  245.         ULONG msgid = (MSG_USER_MESSAGE & MASK_MESSAGE);
  246.  
  247.         /* compute message id */
  248.         if (!upstrcmp(msg_class, "WARNING"))
  249.             msgid |= MSG_WARN;
  250.         else if (!upstrcmp(msg_class, "ERROR"))
  251.             msgid |= MSG_ERROR;
  252.         else if (!upstrcmp(msg_class, "FATAL"))
  253.             msgid |= MSG_FATAL;
  254.         else
  255.         {
  256.             D(if (upstrcmp(msg_class, "NOTE"))
  257.               panic("illegal user message class")
  258.                 );
  259.         }
  260.  
  261.         /* display message */
  262.         hsc_message(hp, msgid, "user message: %s", msg_text);
  263.     }
  264.     return (FALSE);
  265. }
  266.  
  267. /*
  268.  *-------------------------------------
  269.  * $EXEC handle
  270.  *-------------------------------------
  271.  */
  272.  
  273. /*
  274.  * handle_hsc_exec
  275.  *
  276.  * execute shell command
  277.  */
  278. BOOL handle_hsc_exec(HSCPRC * hp, HSCTAG * tag)
  279. {
  280. #ifdef AMIGA
  281. #define TMP_PREFIX "t:hsc"
  282. #else
  283. #define TMP_PREFIX "hsc"
  284. #endif
  285.     STRPTR cmd = get_vartext_byname(tag->attr, "COMMAND");
  286.     HSCATTR *file_attr = find_varname(tag->attr, "FILE");
  287.     HSCATTR *remove_attr = find_varname(tag->attr, "REMOVE");
  288.     HSCATTR *result_attr = find_varname(hp->defattr, RESULT_ATTR);
  289.  
  290.     if (cmd && file_attr && result_attr && remove_attr)
  291.     {
  292.         int result = 0;
  293.         BOOL remove_file = FALSE;
  294.         BOOL read_file = FALSE;
  295.         STRPTR remove_str = get_vartext(remove_attr);
  296.         EXPSTR *msg = init_estr(0);
  297.         EXPSTR *cmdstr = init_estr(32);
  298.  
  299.         /* additional attributes */
  300.         HSCATTR *temp_attr = find_varname(tag->attr, "TEMPORARY");
  301.         HSCATTR *include_attr = find_varname(tag->attr, "INCLUDE");
  302.         HSCATTR *attribute_attr = find_varname(tag->attr, "ATTRIBUTE");
  303.         STRPTR attribute_name = NULL;
  304.         BOOL temporary = get_varbool(temp_attr);
  305.         BOOL include = get_varbool(include_attr);
  306.         BOOL pre = get_varbool_byname(tag->attr, "PRE");
  307.         BOOL source = get_varbool_byname(tag->attr, "SOURCE");
  308.         LONG indent = get_varnum_byname(tag->attr, "INDENT");
  309.         LONG tabsize = get_varnum_byname(tag->attr, "TABSIZE");
  310.  
  311.         INFILE *outfile = NULL;
  312.         STRPTR filename = get_vartext(file_attr);
  313.         BOOL usetmpfile = FALSE;
  314.         ULONG old_msg_count = hp->msg_count;
  315.  
  316.         /* check, if file should be read after execution */
  317.         if (attribute_attr)
  318.             attribute_name = get_vartext(attribute_attr);
  319.         if (attribute_name || include)
  320.             read_file = TRUE;
  321.  
  322.         /* check, if output should be redirected to temp. file */
  323.         if (!filename && read_file)
  324.         {
  325.             usetmpfile = TRUE;
  326.             set_vartext(file_attr, tmpnamstr(TMP_PREFIX));
  327.             set_varbool(temp_attr, TRUE);
  328.             filename = get_vartext(file_attr);
  329.             D(fprintf(stderr, DHL "  use temp-file `%s'\n", filename));
  330.         }
  331.         else
  332.         {
  333.             D(fprintf(stderr, DHL "  use file `%s'\n", filename));
  334.         }
  335.  
  336.         /* check, if output-file should be removed */
  337.         if (remove_str)
  338.         {
  339.             if (!upstrcmp(remove_str, "ON"))
  340.             {
  341.                 remove_file = TRUE;
  342.                 temporary = TRUE;
  343.                 D(fprintf(stderr, DHL "  auto-temporary (remove=ON)\n"));
  344.             }
  345.             else if (!upstrcmp(remove_str, "AUTO"))
  346.                 if (hp->msg_count == old_msg_count)
  347.                 {
  348.                     remove_file = temporary;
  349.                     D(if (!remove_file)
  350.                       fprintf(stderr, DHL "  no auto-remove (temp)\n"));
  351.                 }
  352.                 else
  353.                 {
  354.                     D(fprintf(stderr, DHL "  no auto-remove (count)\n"));
  355.                 }
  356.         }
  357.  
  358.         /* status message */
  359.         app_estr(msg, "execute: ");
  360.         app_estr(msg, cmd);
  361.         hsc_status_misc(hp, estr2str(msg));
  362.  
  363.         /* create command string */
  364.         set_estr(cmdstr, cmd);
  365.         if (usetmpfile)
  366.         {
  367.             app_estr(cmdstr, " >");
  368.             app_estr(cmdstr, filename);
  369.         }
  370.  
  371.         D(fprintf(stderr, DHL "  command=`%s'\n", estr2str(cmdstr)));
  372.  
  373.         /* call command */
  374.         result = system(estr2str(cmdstr));
  375.  
  376.         /* check for non-zero-result */
  377.         if (result)
  378.         {
  379.             hsc_message(hp, MSG_SYSTEM_RETURN,
  380.                         "shell-command returned %d", result);
  381.         }
  382.  
  383.         /* read output to HSC.STDOUT */
  384.         if (read_file)
  385.         {
  386.             errno = 0;
  387.             outfile = infopen(filename, 512);
  388.             if (outfile)
  389.             {
  390.                 /* read to attribute */
  391.                 if (attribute_name)
  392.                 {
  393.                     HSCATTR *output_attr =
  394.                     find_varname(hp->defattr, attribute_name);
  395.  
  396.                     D(fprintf(stderr, DHL "  ATTRIB exec-output to `%s'\n",
  397.                               attribute_name));
  398.  
  399.                     if (output_attr)
  400.                         set_vartext(output_attr, infgetall(outfile));
  401.                     else
  402.                         hsc_msg_unkn_attr(hp, attribute_name);
  403.                 }
  404.                 infclose(outfile);
  405.  
  406.                 /* include output */
  407.                 if (include)
  408.                 {
  409.                     /*handle_hsc_include(hp, tag); */
  410.                     BOOL nostatus = usetmpfile;
  411.                     D(fprintf(stderr, DHL "  INCLUDE exec-output\n"));
  412.                     do_include(hp, get_vartext(file_attr), nostatus,
  413.                                temporary, source, pre, indent, tabsize);
  414.                 }
  415.             }
  416.             else
  417.             {
  418.                 /* couldn't open exec-output file for input */
  419.                 hsc_msg_noinput(hp, filename);
  420.             }
  421.  
  422.             /* check, if output-file should be removed */
  423.             remove_file = FALSE;
  424.             if (remove_str)
  425.             {
  426.                 if (!upstrcmp(remove_str, "ON"))
  427.                     remove_file = TRUE;
  428.                 if (!upstrcmp(remove_str, "AUTO"))
  429.                     if (hp->msg_count == old_msg_count)
  430.                     {
  431.                         remove_file = temporary;
  432.                         D(if (!remove_file)
  433.                           fprintf(stderr, DHL "  no auto-remove (temp)\n"));
  434.                     }
  435.                     else
  436.                     {
  437.                         D(fprintf(stderr, DHL "  no auto-remove (count)\n"));
  438.                     }
  439.             }
  440.  
  441.             /* remove output file */
  442.             if (remove_file)
  443.             {
  444.                 D(fprintf(stderr, DHL "  remove `%s'\n", filename));
  445.                 remove(filename);
  446.             }
  447.         }
  448.         else
  449.         {
  450.             D(fprintf(stderr, DHL "  don't read exec-output\n"));
  451.         }
  452.  
  453.         /* update result-attribute */
  454.         if (result_attr)
  455.         {
  456.             set_vartext(result_attr, long2str((LONG) result));
  457.         }
  458.         else
  459.         {
  460.             D(panic("no result-attribute"));
  461.         }
  462.  
  463.         del_estr(cmdstr);
  464.         del_estr(msg);
  465.     }
  466.     else
  467.         panic("attribute missing");
  468.  
  469.     return (FALSE);
  470. }
  471.  
  472. /*
  473.  *-------------------------------------
  474.  * $EXPORT handle
  475.  *-------------------------------------
  476.  */
  477.  
  478. /*
  479.  * handle_hsc_export
  480.  *
  481.  * execute shell command
  482.  */
  483. BOOL handle_hsc_export(HSCPRC * hp, HSCTAG * tag)
  484. {
  485.     STRPTR filename = get_vartext_byname(tag->attr, "FILE");
  486.     STRPTR data = get_vartext_byname(tag->attr, "DATA");
  487.     BOOL append = get_varbool_byname(tag->attr, "APPEND");
  488.  
  489.     if (filename && data)
  490.     {
  491.         FILE *outfile = NULL;
  492.         STRPTR writemode = "w";
  493.  
  494.         if (append)
  495.             writemode = "a";
  496.  
  497.         errno = 0;
  498.         outfile = fopen(filename, writemode);
  499.         if (outfile)
  500.         {
  501.             fwrite(data, sizeof(char), strlen(data), outfile);
  502.             fclose(outfile);
  503.         }
  504.  
  505.         if (errno)
  506.         {
  507.             hsc_message(hp, MSG_IOERROR, "error opening/writting %q: %s",
  508.                         filename, strerror(errno));
  509.         }
  510.     }
  511.     else
  512.     {
  513.         panic("attribute missing");
  514.     }
  515.     return (FALSE);
  516. }
  517.  
  518. /*
  519.  *-------------------------------------
  520.  * $INSERT handle
  521.  *-------------------------------------
  522.  */
  523.  
  524. /*
  525.  * handle_hsc_time
  526.  *
  527.  * insert current time
  528.  */
  529. BOOL handle_hsc_time(HSCPRC * hp, HSCTAG * tag)
  530. {
  531.     STRPTR timefmt = get_vartext_byname(tag->attr, "FORMAT");
  532.     EXPSTR *timebuf = init_estr(TIMEBUF_INC);
  533.     BOOL strftrc = 0;           /* result of strftime() */
  534.     size_t i;                   /* loop var */
  535.  
  536.     /* set default time format */
  537.     if (!timefmt)
  538.         timefmt = "%d-%b-%Y, %H:%M";
  539.  
  540.     while (!(hp->fatal) && !strftrc)
  541.     {
  542.         /* expand timebuffer */
  543.         for (i = 0; i < TIMEBUF_INC; i++)
  544.             app_estrch(timebuf, '.');
  545.  
  546.         D(fprintf(stderr, DHL "  timebuf: inc+%d\n", TIMEBUF_INC));
  547.  
  548.         /* output time */
  549.         strftrc = strftime(estr2str(timebuf), estrlen(timebuf),
  550.                            timefmt, localtime(&(hp->start_time)));
  551.     }
  552.     if (strftrc)
  553.     {
  554.         INFILEPOS *base = new_infilepos(hp->inpf);
  555.         hsc_base_include_string(hp, SPECIAL_FILE_ID "insert time",
  556.                                 estr2str(timebuf),
  557.                                 IH_PARSE_HSC | IH_NO_STATUS, base);
  558.         del_infilepos(base);
  559.     }
  560.     del_estr(timebuf);
  561.  
  562.     return (FALSE);
  563. }
  564.  
  565. /*
  566.  * handle_hsc_text
  567.  *
  568.  * insert text
  569.  */
  570. BOOL handle_hsc_text(HSCPRC * hp, HSCTAG * tag)
  571. {
  572.     STRPTR text = get_vartext_byname(tag->attr, "TEXT");
  573.  
  574.     /* include text */
  575.     INFILEPOS *base = new_infilepos(hp->inpf);
  576.     hsc_base_include_string(hp, SPECIAL_FILE_ID "insert TEXT", text,
  577.                             IH_PARSE_HSC | IH_NO_STATUS, base);
  578.     del_infilepos(base);
  579.  
  580.     return (FALSE);
  581. }                               /*
  582.                                  * hsc_insert
  583.                                  *
  584.                                  * main insert handle
  585.                                  */
  586. BOOL handle_hsc_insert(HSCPRC * hp, HSCTAG * tag)
  587. {
  588.     BOOL insert_text = FALSE;
  589.     BOOL insert_time = get_varbool_byname(tag->attr, HSC_TIME_STR);
  590.  
  591.     if (get_vartext_byname(tag->attr, HSC_TEXT_STR))
  592.         insert_text = TRUE;
  593.  
  594.     if (insert_text)
  595.         handle_hsc_text(hp, tag);
  596.     else if (insert_time)
  597.         handle_hsc_time(hp, tag);
  598.     else
  599.     {
  600.  
  601.         /* unknown option for $insert */
  602.         hsc_message(hp, MSG_MISS_REQ_ATTR,
  603.                     "required attribute for %t missing", HSC_INSERT_STR);
  604.     }                           /* clear attributes */
  605.     clr_varlist(tag->attr);
  606.  
  607.     return (FALSE);
  608. }
  609.  
  610. /*
  611.  *-------------------------------------
  612.  * <$DEFTAG> define a new tag
  613.  *-------------------------------------
  614.  */
  615. BOOL handle_hsc_deftag(HSCPRC * hp, HSCTAG * tag)
  616. {
  617.     BOOL ok = FALSE;
  618.     BOOL open_tag = FALSE;
  619.  
  620.     tag = def_tag_name(hp, &open_tag);
  621.     ok = (tag && def_tag_args(hp, tag));
  622.  
  623.     return (FALSE);
  624. }
  625.  
  626. /*
  627.  *-------------------------------------
  628.  * <$DEFENT> define a new entity
  629.  *-------------------------------------
  630.  */
  631. static VOID msg_illg_defent(HSCPRC * hp, STRPTR msg)
  632. {
  633.     hsc_message(hp, MSG_ILLG_DEFENT,
  634.                 "illegal entity definition (%s)", msg);
  635. }
  636. BOOL handle_hsc_defent(HSCPRC * hp, HSCTAG * tag)
  637. {
  638.     STRPTR name = get_vartext_byname(tag->attr, "NAME");
  639.     STRPTR rplc = get_vartext_byname(tag->attr, "RPLC");
  640.     STRPTR nums = get_vartext_byname(tag->attr, "NUM");
  641.     LONG num = 0;
  642.  
  643.     if (nums)
  644.     {
  645.         if (str2long(nums, &num))
  646.             if (strlen(rplc) == 1)
  647.                 if ((num >= 160) && (num <= 255))
  648.                 {
  649.                     DLNODE *nd = NULL;
  650.  
  651.                     nd = find_dlnode(
  652.                                 hp->defent->first, (APTR) name, cmp_strent);
  653.                     if (nd)
  654.                         msg_illg_defent(hp, "duplicate entity");
  655.                     else
  656.                     {
  657.                         nd = find_dlnode(
  658.                                  hp->defent->first, (APTR) num, cmp_nument);
  659.                         if (nd)
  660.                             msg_illg_defent(hp, "duplicate NUM");
  661.                     }
  662.                     if (!nd)
  663.                         add_ent(hp->defent, name, rplc, num);
  664.                 }
  665.                 else
  666.                     msg_illg_defent(hp, "illegal range for NUM");
  667.             else
  668.                 msg_illg_defent(hp, "RPLC not a single character");
  669.         else
  670.             msg_illg_defent(hp, "illegal value for NUM");
  671.     }
  672.     else
  673.         msg_illg_defent(hp, "RPLC and/or NUM missing");
  674.  
  675.     return (FALSE);
  676. }
  677.  
  678. /*
  679.  *-------------------------------------
  680.  * <$DEFICON> define a new icon-entity
  681.  *-------------------------------------
  682.  */
  683. BOOL handle_hsc_deficon(HSCPRC * hp, HSCTAG * tag)
  684. {
  685.     STRPTR name = get_vartext_byname(tag->attr, "NAME");
  686.     DLNODE *nd = NULL;
  687.  
  688.     nd = find_dlnode(hp->defent->first, (APTR) name, cmp_strent);
  689.     if (nd)
  690.         msg_illg_defent(hp, "duplicate entity");
  691.     else
  692.         add_ent(hp->defent, name, NULL, ICON_ENTITY);
  693.  
  694.     return (FALSE);
  695. }
  696. /*
  697.  *-------------------------------------
  698.  * <$DEFINE> create a new (global) attribute
  699.  *-------------------------------------
  700.  */
  701. BOOL handle_hsc_define(HSCPRC * hp, HSCTAG * tag)
  702. {
  703.     HSCVAR *attr = define_var(hp, hp->defattr, 0); /* TODO: define local macro attributes */
  704.     if (attr)
  705.     {
  706.         /* set mci for local attribute */
  707.         if (attr->varflag & VF_GLOBAL)
  708.             attr->macro_id = MCI_GLOBAL;
  709.         else
  710.             attr->macro_id = get_current_mci(hp);
  711.  
  712.         /* see "attrib.h" why this */
  713.         attr->varflag |= VF_MACRO;
  714.  
  715.         /* set new value (copy from default) if passed */
  716.         if (get_vardeftext(attr))
  717.             clr_vartext(attr);
  718.  
  719.         /* remove default value */
  720.         clr_attrdef(attr);
  721.  
  722.         DDA(prt_varlist(hp->defattr, "attributes after $DEFINE"));
  723.  
  724.         /* check for closing ">" */
  725.         parse_gt(hp);
  726.  
  727.     }
  728.     return (FALSE);
  729. }
  730.  
  731. /*
  732.  *-------------------------------------
  733.  * <$LET> set/reset/clear attribute value
  734.  *-------------------------------------
  735.  */
  736. BOOL handle_hsc_let(HSCPRC * hp, HSCTAG * tag)
  737. {
  738.     INFILE *inpf = hp->inpf;
  739.     STRPTR varname = infgetw(inpf);
  740.     HSCVAR *attr = NULL;
  741.     BOOL ok = FALSE;
  742.  
  743.     if (varname)
  744.     {
  745.         /* create temporary dummy attribute that is
  746.          * used to store the value, if attribute
  747.          * passed is a constant
  748.          */
  749.         HSCVAR *dummy = new_hscattr(PREFIX_TMPATTR "let");
  750.  
  751.         /* find attribute */
  752.         attr = find_varname(hp->defattr, varname);
  753.         if (attr)
  754.         {
  755.             STRPTR eq_sign = infgetw(inpf);
  756.  
  757.             if (attr->varflag & VF_CONST)
  758.             {
  759.                 /* tried to set constant */
  760.                 hsc_message(hp, MSG_ATTR_CONST,
  761.                             "attempt to modify constant %A", attr);
  762.  
  763.                 /* assign destination to dummy attribute */
  764.                 attr = dummy;
  765.                 dummy->vartype = attr->vartype;
  766.                 dummy->varflag = attr->varflag;
  767.             }
  768.  
  769.             /* check if a "=" comes next */
  770.             if (eq_sign && !strcmp(eq_sign, "="))
  771.                 /* Y->get new value */
  772.                 eval_expression(hp, attr, NULL);
  773.             else
  774.             {
  775.                 /* N->clear or reset attribute to default value */
  776.                 clr_vartext(attr);
  777.                 /* write previous word back (should be ">") */
  778.                 inungetcw(inpf);
  779.             }
  780.  
  781.             DDA(prt_varlist(hp->defattr, "attributes after $LET"));
  782.  
  783.             /* check for closing ">" */
  784.             ok = parse_gt(hp);
  785.         }
  786.         else
  787.             hsc_msg_unkn_attr(hp, varname);
  788.  
  789.         /* remove dummy attribute */
  790.         del_hscattr(dummy);
  791.  
  792.     }
  793.     return (FALSE);
  794. }
  795.  
  796. /*
  797.  *-------------------------------------
  798.  * <$SOURCE> include a source part
  799.  *-------------------------------------
  800.  */
  801. BOOL handle_hsc_source(HSCPRC * hp, HSCTAG * tag)
  802. {
  803.     INFILE *inpf = hp->inpf;
  804.     BOOL pre = get_varbool_byname(tag->attr, "PRE");
  805.     BOOL ok = TRUE;
  806.     EXPSTR *bufstr = NULL;
  807.     EXPSTR *srcstr = NULL;
  808.     BYTE state = SRST_TEXT;
  809.     STRPTR nw = NULL;
  810.     INFILEPOS *base = new_infilepos(hp->inpf);
  811.  
  812.     /*
  813.      * read until </$SOURCE> found
  814.      */
  815.  
  816.     /* init bufstr */
  817.     bufstr = init_estr(ES_STEP_SOURCE);
  818.     srcstr = init_estr(ES_STEP_SOURCE);
  819.  
  820.     /* avoid nesting of <PRE> */
  821.     if (hp->inside_pre)
  822.         pre = FALSE;            /* TODO: lauch warning */
  823.  
  824.     /* insert leading <PRE> */
  825.     if (pre)
  826.     {
  827.         hsc_include_string(hp, SPECIAL_FILE_ID "insert <PRE>", "<PRE>",
  828.                            IH_PARSE_HSC | IH_NO_STATUS | IH_POS_PARENT);
  829.     }
  830.  
  831.     while (!((hp->fatal) || (state == SRST_CSOURCE)))
  832.     {
  833.  
  834.         /* read next word */
  835.         if (state == SRST_SLASH)
  836.             nw = infget_tagid(hp);
  837.         else if (state != SRST_TAG)
  838.             nw = infgetw(inpf);
  839.  
  840.         if (nw)
  841.         {
  842.             if (state == SRST_TAG)
  843.             {
  844.                 /*
  845.                  * skip inside tags
  846.                  */
  847.                 BYTE tag_state = TGST_TAG;      /* state var passe to */
  848.                 /*     eot_reached() */
  849.  
  850.                 do
  851.                 {
  852.                     if (eot_reached(hp, &tag_state))
  853.                         state = SRST_TEXT;
  854.  
  855.                     app_estr(srcstr, infgetcws(inpf));
  856.                     app_estr(srcstr, infgetcw(inpf));
  857.                 }
  858.                 while ((tag_state != TGST_END) && !(hp->fatal));
  859.             }
  860.             else
  861.             {
  862.                 switch (state)
  863.                 {
  864.                 case SRST_TEXT:
  865.                     if (!strcmp(nw, "<"))
  866.                         state = SRST_LT;
  867.                     break;
  868.  
  869.                 case SRST_LT:
  870.                     if (!strcmp(nw, "/"))
  871.                         state = SRST_SLASH;
  872.                     else
  873.                         state = SRST_TEXT;
  874.                     break;
  875.  
  876.                 case SRST_SLASH:
  877.                     if (!upstrcmp(nw, HSC_SOURCE_STR))
  878.                         state = SRST_CSOURCE;   /* end of source */
  879.                     else
  880.                         state = SRST_TEXT;
  881.                     break;
  882.  
  883.                 }
  884.  
  885.                 if (state == SRST_TEXT)
  886.                 {
  887.                     /* append bufstr to srcstr, clear bufstr,
  888.                      * append current word to srcstr
  889.                      */
  890.                     if (estrlen(bufstr))
  891.                     {
  892.                         app_estr(srcstr, estr2str(bufstr));
  893.                         clr_estr(bufstr);
  894.                     }
  895.                     app_estr(srcstr, infgetcws(inpf));
  896.                     app_estr(srcstr, infgetcw(inpf));
  897.                 }
  898.                 else
  899.                 {
  900.                     /* append data to bufstr */
  901.                     app_estr(bufstr, infgetcws(inpf));
  902.                     app_estr(bufstr, infgetcw(inpf));
  903.                 }
  904.             }
  905.         }
  906.         else
  907.         {
  908.             hsc_msg_eof(hp, "missing </" HSC_SOURCE_STR ">");
  909.             state = SRST_ERR;
  910.         }
  911.     }                           /* while */
  912.  
  913.     /* check for legal end state */
  914.     if (state == SRST_CSOURCE)
  915.     {
  916.         ok = parse_wd(hp, ">");
  917.     }
  918.     /* include source */
  919.     if (ok)
  920.     {
  921.         /* include pseudo-file */
  922.         hsc_base_include_string(hp, SPECIAL_FILE_ID "source",
  923.                                 estr2str(srcstr),
  924.                                 IH_PARSE_SOURCE | IH_NO_STATUS, base);
  925.  
  926.         /* insert tailing </PRE> */
  927.         if (pre)
  928.         {
  929.             hsc_include_string(hp, SPECIAL_FILE_ID "insert </PRE>",
  930.                                "</PRE>\n",
  931.                                IH_PARSE_HSC | IH_NO_STATUS | IH_POS_PARENT);
  932.         }
  933.     }
  934.     del_infilepos(base);
  935.     del_estr(bufstr);
  936.     del_estr(srcstr);
  937.  
  938.     return (FALSE);
  939. }
  940.  
  941.